home *** CD-ROM | disk | FTP | other *** search
- /* Definitions for the new event model;
- created 16-jul-91 by Jamie Zawinski
- Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
-
- This file is part of XEmacs.
-
- XEmacs is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- XEmacs is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with XEmacs; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Synched up with: Not in FSF. */
-
- #ifndef _XEMACS_EVENTS_H_
- #define _XEMACS_EVENTS_H_
-
- #include "systime.h"
-
- /* There is one object, called an event_stream. This object contains
- callback functions for doing the window-system dependent operations that
- emacs requires.
-
- If emacs is compiled with support for X11 and the X Toolkit, then this
- event_stream structure will contain functions that can cope with input
- on emacs windows on multiple displays, as well as input from dumb tty
- frames.
-
- If it is desired to have emacs able to open frames on the displays of
- multiple heterogeneous machines, X11 and SunView, or X11 and NeXT, for
- example, then it will be necessary to construct an event_stream structure
- that can cope with the given types. Currently, the only implemented
- event_streams are for dumb-ttys, and for X11 plus dumb-ttys.
-
- To implement this for one window system is relatively clean and simple.
- To implement this for multiple window systems is hard and hairy, so we
- are punting for now.
-
- The slots of the event_stream structure:
-
- next_event_cb A function which fills in an emacs_event struture
- with the next event available. If there is no event
- available, then this should block.
-
- IMPORTANT: timer events and especially process
- events *must not* be returned if there are
- events of other types available; otherwise you
- can end up with an infinite loop in Fdiscard_input().
-
- event_pending_cb A function which says whether there are events to be
- read. If called with an argument of 0, then this
- should say whether calling the next_event_cb will
- block. If called with an argument of 1, then this
- should say whether there are user-generated events
- pending (that is, keypresses or mouse-clicks). This
- is used for redisplay optimization, among other
- things. On dumb ttys, these two results are the
- same, but under a window system, they are not.
-
- If this function is not sure whether there are events
- to be read, it *must* return 0. Otherwise various
- undesirable effects will occur, such as redisplay
- not occurring until the next event occurs.
-
- handle_magic_event_cb Emacs calls this with an event structure which
- contains window-system dependent information that
- emacs doesn't need to know about, but which must
- happen in order. If the next_event_cb never returns
- an event of type "magic", this will never be used.
-
- add_timeout_cb Called with an EMACS_TIME, the absolute time at
- which a wakeup event should be generated; and a
- void *, which is an arbitrary value that will be
- returned in the timeout event. The timeouts
- generated by this function should be one-shots:
- they fire once and then disappear. This callback
- should return an int id-number which uniquely
- identifies this wakeup. If an implementation
- doesn't have microseconds or millisecond
- granularity, it should round up to the closest
- value it can deal with.
-
- remove_timeout_cb Called with an int, the id number of a wakeup to
- discard. This id number must have been returned by
- the add_timeout_cb. If the given wakeup has
- already expired, this should do nothing.
-
- select_process_cb These callbacks tell the underlying implementation to
- unselect_process_cb add or remove a file descriptor from the list of fds
- which are polled for inferior-process input. When
- input becomes available on the given process
- connection, an event of type "process" should be
- generated.
-
- select_device_cb These callbacks tell the underlying implementation
- unselect_device_cb to add or remove a device from the list of devices
- which are polled for user-input.
-
- quitp_cb A handler function called from the `QUIT' macro which
- should check whether the quit character has been
- typed. On systems with SIGIO, this will not be called
- unless the `sigio_happened' flag is true (it is set
- from the SIGIO handler).
-
- Emacs has its own event structures, which are distinct from the event
- structures used by X or any other window system. It is the job of the
- event_stream layer to translate to this format.
-
- NOTE: All timestamps are measured as milliseconds since Emacs started.
-
- key_press_event
- event_channel A token representing which keyboard generated it.
- For this kind of event, this is a frame object.
- timestamp When it happened
- key What keysym this is; an integer or a symbol.
- If this is an integer, it will be in the printing
- ASCII range: >32 and <127.
- modifiers Bucky-bits on that key: control, meta, etc.
- For most keys, Shift is not a bit; that is implicit
- in the keyboard layout.
-
- button_press_event
- button_release_event
- event_channel A token representing which mouse generated it.
- For this kind of event, this is a frame object.
- timestamp When it happened
- button What button went down or up.
- modifiers Bucky-bits on that button: shift, control, meta, etc.
- x, y Where it was at the button-state-change (in pixels).
-
- pointer_motion_event
- event_channel A token representing which mouse generated it.
- For this kind of event, this is a frame object.
- timestamp When it happened
- x, y Where it was after it moved (in pixels).
- modifiers Bucky-bits down when the motion was detected.
- (Possibly not all window systems will provide this?)
-
- process_event
- timestamp When it happened
- process the emacs "process" object in question
-
- timeout_event
- timestamp Now (really, when the timeout was signalled)
- interval_id The ID returned when the associated call to
- add_timeout_cb() was made
- ------ the rest of the fields are filled in by Emacs -----
- id_number The Emacs timeout ID for this timeout (more
- than one timeout event can have the same value
- here, since Emacs timeouts, as opposed to
- add_timeout_cb() timeouts, can resignal
- themselves)
- function An elisp function to call when this timeout is
- processed.
- object The object passed to that function.
-
- eval_event
- timestamp When it happened
- function An elisp function to call with this event object.
- object Anything.
- This kind of event is used internally; sometimes the
- window system interface would like to inform emacs of
- some user action (such as focusing on another frame)
- but needs that to happen synchronously with the other
- user input, like keypresses. This is useful when
- events are reported through callbacks rather
- than in the standard event stream.
-
- misc_user_event
- timestamp When it happened
- function An elisp function to call with this event object.
- object Anything.
- This is similar to an eval_event, except that it is
- generated by user actions: selections in the
- menubar or scrollbar actions. It is a "command"
- event, like key and mouse presses (and unlike mouse
- motion, process output, and enter and leave window
- hooks). In many ways, eval_events are not the same
- as keypresses or misc_user_events.
-
- magic_event
- No user-serviceable parts within. This is for things
- like KeymapNotify and ExposeRegion events and so on
- that emacs itself doesn't care about, but which it
- must do something with for proper interaction with
- the window system.
-
- Magic_events are handled somewhat asynchronously, just
- like subprocess filters. However, occasionally a
- magic_event needs to be handled synchronously; in that
- case, the asynchronous handling of the magic_event will
- push an eval_event back onto the queue, which will be
- handled synchronously later. This is one of the
- reasons why eval_events exist; I'm not entirely happy
- with this aspect of this event model.
- */
-
-
- struct Lisp_Event;
- struct Lisp_Process;
-
- struct event_stream
- {
- int (*event_pending_p) (int);
- void (*next_event_cb) (struct Lisp_Event *);
- void (*handle_magic_event_cb) (struct Lisp_Event *);
- int (*add_timeout_cb) (EMACS_TIME);
- void (*remove_timeout_cb) (int);
- void (*select_device_cb) (struct device *);
- void (*unselect_device_cb) (struct device *);
- void (*select_process_cb) (struct Lisp_Process *);
- void (*unselect_process_cb) (struct Lisp_Process *);
- void (*quit_p_cb) (void);
- };
-
-
- extern struct event_stream *event_stream;
-
- typedef enum emacs_event_type
- {
- empty_event,
- key_press_event,
- button_press_event,
- button_release_event,
- pointer_motion_event,
- process_event,
- timeout_event,
- magic_event,
- eval_event,
- misc_user_event,
- dead_event
- } emacs_event_type;
-
- #define first_event_type empty_event
- #define last_event_type dead_event
-
-
- struct key_data
- {
- Lisp_Object keysym;
- unsigned char modifiers;
- };
-
- struct button_data
- {
- int button;
- unsigned char modifiers;
- int x, y;
- };
-
- struct motion_data
- {
- int x, y;
- unsigned char modifiers;
- };
-
- struct process_data
- {
- Lisp_Object process;
- };
-
- struct timeout_data
- {
- int interval_id;
- int id_number;
- Lisp_Object function, object;
- };
-
- struct eval_data
- {
- Lisp_Object function;
- Lisp_Object object;
- };
-
- #if defined (HAVE_X_WINDOWS) && defined(emacs)
- # include <X11/Xlib.h>
- #endif
-
- #if defined (HAVE_NEXTSTEP) && defined(emacs)
- # import <appkit/appkit.h>
- #endif
-
- union magic_data
- {
- char underlying_tty_event;
- #ifdef HAVE_X_WINDOWS
- XEvent underlying_x_event;
- #endif
- #ifdef HAVE_NEXTSTEP
- NXEvent underlying_ns_event;
- #endif
- };
-
- struct Lisp_Event
- {
- /* header->next (aka event_next ()) is used as follows:
- - For dead events, this is the next dead one.
- - For events on the command_event_queue, the next one on the queue.
- - Otherwise it's 0.
- */
- struct lrecord_header lheader;
- struct Lisp_Event *next;
- emacs_event_type event_type;
- Lisp_Object channel;
- Lisp_Object device;
- unsigned int timestamp;
- union
- {
- struct key_data key;
- struct button_data button;
- struct motion_data motion;
- struct process_data process;
- struct timeout_data timeout;
- struct eval_data eval; /* misc_user_event uses this too */
- union magic_data magic;
- } event;
- };
-
- DECLARE_LRECORD (event, struct Lisp_Event);
- #define XEVENT(x) XRECORD (x, event, struct Lisp_Event)
- #define XSETEVENT(x, p) XSETRECORD (x, p, event)
- #define EVENTP(x) RECORDP (x, event)
- #define CHECK_EVENT(x, i) CHECK_RECORD (x, event)
-
- #define EVENT_DEVICE(a) ((a)->device)
- #define EVENT_TYPE(a) ((a)->event_type)
- #define event_next(a) ((a)->next)
- #define set_event_next(a, n) do { ((a)->next = (n)); } while (0)
-
- #define EVENT_LIVE_P(a) (EVENT_TYPE (a) != dead_event)
-
- #define CHECK_LIVE_EVENT(x, i) \
- do { CHECK_EVENT (x, i); \
- if (! EVENTP (x) \
- || ! EVENT_LIVE_P (XEVENT (x))) \
- x = wrong_type_argument (Qevent_live_p, (x)); } while (0)
-
-
- extern Lisp_Object Qevent_live_p;
-
- /* The modifiers emacs knows about; these appear in key and button events.
- */
- #define MOD_CONTROL (1<<0)
- #define MOD_META (1<<1)
- #define MOD_SUPER (1<<2)
- #define MOD_HYPER (1<<3)
- #define MOD_ALT (1<<4)
- #define MOD_SHIFT (1<<5) /* not used for dual-case characters */
-
- /* Note: under X Windows, MOD_ALT is generated by the Alt key if there are
- both Alt and Meta keys. If there are no Meta keys, then Alt generates
- MOD_META instead.
- */
-
- #ifdef emacs
- /* Maybe this should be trickier */
- #define KEYSYM(x) (intern (x))
-
- extern void format_event_object (char *buf, struct Lisp_Event *e, int brief);
- extern void character_to_event (Emchar c, struct Lisp_Event *event,
- struct device *d);
-
-
- /* True is this is a non-internal event
- (keyboard press, menu, scrollbar, mouse button) */
- extern int command_event_p (struct Lisp_Event *event);
-
- extern int event_stream_event_pending_p (int user);
- extern void event_stream_next_event (struct Lisp_Event *event);
- extern void event_stream_handle_magic_event (struct Lisp_Event *event);
- extern void event_stream_select_device (struct device *d);
- extern void event_stream_unselect_device (struct device *d);
- extern void event_stream_select_process (struct Lisp_Process *proc);
- extern void event_stream_unselect_process (struct Lisp_Process *proc);
- extern void event_stream_quit_p (void);
-
- struct low_level_timeout
- {
- int id;
- EMACS_TIME time;
- struct low_level_timeout *next;
- };
-
- extern int add_low_level_timeout (struct low_level_timeout **timeout_list,
- EMACS_TIME time);
- extern void remove_low_level_timeout (struct low_level_timeout **timeout_list,
- int id);
- extern int get_low_level_timeout_interval (struct low_level_timeout *
- timeout_list, EMACS_TIME *interval);
- extern int pop_low_level_timeout (struct low_level_timeout **timeout_list,
- EMACS_TIME *time_out);
-
- extern int event_stream_generate_wakeup (unsigned int milliseconds,
- unsigned int vanilliseconds,
- Lisp_Object function,
- Lisp_Object object,
- int async_p);
- extern void event_stream_deal_with_async_timeout (int interval_id);
-
- /* from signal.c */
- extern int event_stream_add_async_timeout (EMACS_TIME time);
- extern void event_stream_remove_async_timeout (int id);
-
- /* Ceci n'est pas un pipe. */
- extern int signal_event_pipe[];
-
- extern void signal_fake_event (void);
- extern void drain_signal_event_pipe (void);
-
- extern int emacs_is_blocking;
-
- extern Lisp_Object Vcontrolling_terminal;
-
- extern volatile int sigint_happened;
-
- /* Define this if you want the tty event stream to be used when the
- first device is tty, even if HAVE_X_WINDOWS is defined */
- /* #define DEBUG_TTY_EVENT_STREAM */
-
- #endif /* emacs */
-
- #endif /* _XEMACS_EVENTS_H_ */
-